#include "Gorbi.h"
#include "../SGD Wrappers/SGD_Event.h"
#include "../SGD Wrappers/SGD_InputManager.h"
#include "Player.h"
#include "Runner.h"
CGorbi::CGorbi()
{
	Listener::RegisterForEvent("ASSESS_THREAT");
	Listener::RegisterForEvent("TORNADO_SWIRL");

	m_fDamage = 20;
	m_fAttackTimer = 1;
	m_fDefAttack = 1;
}


CGorbi::~CGorbi()
{
	Listener::UnregisterFromEvent("ASSESS_THREAT");
	Listener::UnregisterFromEvent("TORNADO_SWIRL");

}

void CGorbi::Update(float elapsedTime) /*override*/
{
	if (SGD::InputManager::GetInstance()->IsKeyDown(SGD::Key::P))
		m_fCurrStamina = 0;

	if (m_bExhausted == true)
	{
		m_fKnockOutTimer = 3;
		m_TempColor = { 0, 0, 0 };
		m_pBall->SetPosition ({m_ptPosition.x - 32, m_ptPosition.y - 32 });
		m_pBall->SetVelocity({ 0, 0 });
		m_vtVelocity = { 0, 0 };
		//m_ptPosition = m_ptHomePos;
		m_CurrState = IDLE_STATE;
		m_pBall->ToggleActive(true);
		m_bExhausted = false;
		m_fCurrStamina = m_fMaxStamina;
		m_bInRange = false;
	}
	else if (m_fKnockOutTimer <= 0)
	{
		if (m_pBall->GetPosition() != m_ptBallHome)
		{
			if (m_pBall->IsHeld() == true)
				m_tTable.Target = dynamic_cast<CBall*>(m_pBall)->GetOwner();
			else
				m_tTable.Target = m_pBall;

			if (m_tTable.Target != nullptr && SGD::Vector(m_tTable.Target->GetPosition() - m_ptPosition).ComputeLength() > m_fChaseRadius)
				m_fRageTimer -= elapsedTime;
			else
				SwitchStates(CHASE_STATE);
		}

		if (m_fRageTimer <= 0)
			m_bRageMode = true;


		if (m_bRageMode == true)
		{

			if (dynamic_cast<CBall*>(m_pBall)->IsHeld() == true)
				m_tTable.Target = dynamic_cast<CBall*>(m_pBall)->GetOwner();
			else
				m_tTable.Target = m_pBall;

			SwitchStates(CHASE_STATE);
		}
		if (m_fRageTimer <= 0)
			//m_bRageMode = true;

		if (m_bRageMode == true)
			SwitchStates(CHASE_STATE);


		if (SGD::Vector(m_ptHomePos - m_ptPosition).ComputeLength() <= 20
			&& dynamic_cast<CBall*>(m_pBall)->GetOwner() == nullptr)
		{
			m_ptPosition = m_ptHomePos;
			SwitchStates(IDLE_STATE);
			m_bRageMode = false;
			m_fRageTimer = 6;
			m_pBall->ToggleActive(true);
			m_pBall->SetPosition(m_ptBallHome);
			m_tTable.Target = nullptr;
			m_bInRange = false;
			m_pBall->SetAerial(false);
			m_pBall->SetDestPos(m_pBall->GetPosition());
			m_pBall->SetVelocity({ 0, 0 });
		}

		if (m_tTable.Target != nullptr && m_tTable.Target != m_pBall)
		{
			
			if (m_tTable.Target != nullptr)
				SwitchStates(CAI::CHASE_STATE);
		
			if (m_CurrState == CHASE_STATE && m_bInRange == true)
			{
				SwitchStates(ATTACK_STATE);
			}
		}
	}

	if (m_fKnockOutTimer <= 0)
	{
		m_bExhausted = false;
		m_TempColor = { 0, 255, 255 };
		m_bInRange = false;
	}

	if (m_fCurrStamina <= 0)
	{
		m_bExhausted = true;
		m_fKnockOutTimer = 3;
	}

	m_fKnockOutTimer -= elapsedTime;

	CAI::Update(elapsedTime);
}

/*virtual*/ void CGorbi::HandleCollision(const Entity* pOther)	/*override*/
{
	CAgent::HandleCollision(pOther);
	if (pOther->GetType() == ENT_WALL)
	{
		if (m_bRageMode == false)
		{
			// Is the agent in between the wall's top and bottome?
			if (m_ptPosition.y + 1 <= pOther->GetPosition().y + pOther->GetSize().height - 1 &&
				m_ptPosition.y + m_szSize.height - 1 >= pOther->GetPosition().y + 1)
			{
				// is the agent to the left of the wall?
				if (m_ptPosition.x + m_szSize.width > pOther->GetPosition().x && m_ptPosition.x + m_szSize.width < pOther->GetPosition().x + pOther->GetSize().width)
					m_ptPosition.x -= (m_ptPosition.x + m_szSize.width) - pOther->GetPosition().x;
				// is the agent to the right of the wall?
				else if (m_ptPosition.x < pOther->GetPosition().x + pOther->GetSize().width && m_ptPosition.x > pOther->GetPosition().x)
					m_ptPosition.x += (pOther->GetPosition().x + pOther->GetSize().width) - m_ptPosition.x;
			}
			else
			{
				// is the agent above the wall?
				if (m_ptPosition.y + m_szSize.height > pOther->GetPosition().y && m_ptPosition.y + m_szSize.height < pOther->GetPosition().y + pOther->GetSize().height)
					m_ptPosition.y -= (m_ptPosition.y + m_szSize.height) - pOther->GetPosition().y;
				// is the agent below the wall?
				else if (m_ptPosition.y < pOther->GetPosition().y + pOther->GetSize().height && m_ptPosition.y > pOther->GetPosition().y)
					m_ptPosition.y += (pOther->GetPosition().y + pOther->GetSize().height) - m_ptPosition.y;
			}
		}
		else
		{
			SGD::Event* turnOff = new SGD::Event("TURN_OFF");
			turnOff->SendEventNow(pOther);
			delete turnOff;
			turnOff = nullptr;
		}
	}
	else if (pOther->GetType() == ENT_BALL && m_bExhausted == false && m_pBall->GetAerial() == false)
	{
		m_pBall->SetPosition(m_ptBallHome);
		m_pBall->ToggleActive(false);
		dynamic_cast<CBall*>(m_pBall)->SetOwner(dynamic_cast<CPlayer*>(dynamic_cast<Entity*>(this)));
	}
	else if (pOther->GetType() == ENT_PUNCH)
	{
		m_fCurrStamina -= 201;
	}
}

void CGorbi::HandleEvent(const SGD::Event* pEvent) /*override*/
{
	SGD::Vector attackTarget = reinterpret_cast<CPlayer*>(pEvent->GetSender())->GetPosition() - m_ptPosition;

	if (pEvent->GetEventID() == "ASSESS_THREAT")

	{
		if (attackTarget.ComputeLength() <= 100)
			m_tTable.Target = reinterpret_cast<CPlayer*>(pEvent->GetSender());
	}

	if (pEvent->GetEventID() == "TORNADO_SWIRL")
	{
		if (pEvent->GetSender() != this)
		{

			switch (reinterpret_cast<int>(pEvent->GetData()))
			{
			case 1:
			{
					  //check how far I am so I can get effected by the tornado
					  if (SGD::Vector(reinterpret_cast<CRunner*>(pEvent->GetSender())->GetTornadoPos() - this->GetPosition()).ComputeLength() < 75)
						  this->RotatePlayers(this, 0.005f, reinterpret_cast<CRunner*>(pEvent->GetSender())->GetTornadoPos());

			}
				break;
			case 2:
			{
					  //check how far I am so I can get effected by the tornado
				

					  if (SGD::Vector(reinterpret_cast<CRunner*>(pEvent->GetSender())->GetTornadoPos() - this->GetPosition()).ComputeLength() < 150)
						  this->RotatePlayers(this, 0.007f/2.0f, reinterpret_cast<CRunner*>(pEvent->GetSender())->GetTornadoPos());
			}
				break;
			case 3:
			{
					  //check how far I am so I can get effected by the tornado
					

					  if (SGD::Vector(reinterpret_cast<CRunner*>(pEvent->GetSender())->GetTornadoPos() - this->GetPosition()).ComputeLength() < 250)
						  this->RotatePlayers(this, 0.01f/2.0f, reinterpret_cast<CRunner*>(pEvent->GetSender())->GetTornadoPos());
			}
				break;
			default:
				break;
			}
		}
	}

	Entity::HandleEvent(pEvent);
}